/**
 * Created by murmur on 2015/4/5.
 */
var $ = window.$;
var document = window.document;
var event = require('../../core/event');
var timer = require('../../core/timer');
var timing = require('../timing/manager');
var util = require('../../util/index');
var sound = require('../audio/sound');
var sample = require('../sample/manager');
var config = require('../../core/config');
var jade = require('jade');
var io = require('../io/ui');
var inherits = require('util').inherits;
var base = require('./ui.js');
var notify = require('../notify/ui');
var status = require('../toggle/ui');
var frac = require('../../util/frac');
var vector = require('./vector');
var timeline = require('../timeline/ui');
var record = require('../../core/record');
var enums = require('../../core/enum');
var gridUtil = require('./util');


window.CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) {
    if (w < 2 * r){
        r = w / 2;
    }
    if (h < 2 * r){
        r = h / 2;
    }
    this.beginPath();
    this.moveTo(x+r, y);
    this.arcTo(x+w, y, x+w, y+h, r);
    this.arcTo(x+w, y+h, x, y+h, r);
    this.arcTo(x, y+h, x, y, r);
    this.arcTo(x, y, x+w, y, r);
    this.closePath();
    return this;
};

var GridUI = function() {

};

inherits(GridUI, base);
GridUI.prototype._release = base.prototype.release;
GridUI.prototype._onUpdate = base.prototype.onUpdate;
GridUI.prototype._makeNoteDiv = base.prototype.makeNoteDiv;
GridUI.prototype._onEvent = base.prototype.onEvent;
GridUI.prototype._getSelectIds = base.prototype.getSelectIds;
GridUI.prototype._cancelSelect = base.prototype.cancelSelect;
GridUI.prototype._deleteSelect = base.prototype.deleteSelect;
GridUI.prototype._updateNotesPos = base.prototype.updateNotesPos;
GridUI.prototype._updateGrid = base.prototype.updateGrid;
GridUI.prototype._onParentEvent = base.prototype.onParentEvent;

GridUI.prototype.init = function(){
    if(this._init){
        return;
    }
    /*dom操作部分*/
    this.parent = $('#edit_up');
    var template = jade.compileFile('./tmpl/grid/ubeat.jade');
    this.parent.html(template());
    this.editArea = $("#edit_area");
    this.line = $('#grid_line');
    this.grid = $('#grid');
    this.note = $('#note_area');
    this.barline = $('#bar_line');
    this.padEditArea = $('#ubt_edit_area');
    this.select = $('#select_area');
    $("#menu_interval").show();
    $("#hold_hint").html(config.i18n("ubt01"));
    /*拷贝来的东西*/
    this.gridScale = 1.0;  //1 beat的缩放值
    this.divide = 4;
    this._beatH = 100;
    this._noteH = 20;  // 跟css里关联
    this._columnW = 64;
    this._columnCount = 1;
    this._gridBtY = 100;   //栅格0点离底部的px距离
    this.gridScaleH = this._beatH * this.gridScale;  //这两个要联动
    this.gridH = this.grid.height();
    this._gridPadding = 75;
	this._padW = 122;
    /*ubt模式参数*/
    this.markerLen = 833.33;
    this.frameLength = this.markerLen / 25; //一帧的长度
    this.fadeInTime = (14 + 1.5) * this.frameLength; //中心点之前的动画 包括14帧普通判定和1.5帧perfect
    this.fadeOutTime = (8 + 1.5) * this.frameLength; //中心点之后的动画 包括8帧普通判定和1.5帧perfect
    this.rowCount = 4; //每行有多少个touch点
    this.padCanvas = document.getElementById('pad_canvas').getContext('2d');
    this.padEditCanvas = document.getElementById('pad_edit_canvas').getContext('2d');
    /*ubt模式状态量*/
    this.selectedNotes = {}; //touch区域选择的note，保存为note-id:true
    this.centerPos = []; // center positions of each block
	this.musicbar = {};
    this.unplayedNote = [];
    this.playedNote = [];
    this.playingNote = new Array(16);
    this.lastSeekTime = -1;
    /*插件*/
    var plugin = require('./plugin/edit');
    this.pluginEdit = new plugin();
    this.pluginEdit.setUI(this);
    this.pluginPadEdit = require('./plugin/edit-pad');
    this.pluginPadEdit.setUI(this);
    this.pluginCopy = require('./plugin/copy-pad');
    this.pluginCopy.setUI(this);
    this.pluginUndo = require('./plugin/undo');
    this.pluginUndo.init();
    this.pluginUndo.setUI(this);
    plugin = require("./plugin/meta");
    this.pluginMeta = new plugin();
    this.pluginMeta.init();
    this.pluginMeta.setUI(this);
    this.record = record;

    record.init();
    /*初始化函数*/
    this.bind();
    this.bindPadEvents();
    this.calcBlockOffset();
    this.calcBlockCenterPos();
    this.cacheMarker();
};
/*
 * ================================ 继承自父类的函数 ================================
 */

GridUI.prototype.release = function () {
    this._release();
    $("#menu_interval").hide();
    event.unbindByKey('jbt_ui');
};

GridUI.prototype.sync = function(){
    var chart = this.manager.chart;
    var notes = this.manager.getNotes();
    if(!notes){
        return;
    }

    for(var i=0;i<notes.length;i++){
        var note = notes[i];
		note.beat = frac.reduce(note.beat);
        note.time = timing.beatToTime(note.beat);
        if(note.endbeat){
            note.endtime = timing.beatToTime(note.endbeat);
        }
		if(note.index >= 0){
			var key = this.beatToKey(note.beat);
			if(key in this.musicbar){
				this.musicbar[key]++;
			}else{
				this.musicbar[key] = 1;
			}
		}

    }

    this.initSeekQueue();
    this.note.html('');

    var info = this.manager.getEditInfo();
    this.divide = gridUtil.clampDivide(config.getVal(config.ITEM.GRID_DIVI) || 4);
    this.gridScale = config.getVal(config.ITEM.GRID_ZOOM) || 1;
    this.gridScaleH = this.gridScale * this._beatH;

    //重置可编辑区域长度
    var len = 0;
    if(info.grid && info.grid.length){
        len = info.grid.length;
    }else{
        len = this.manager.getMaxNoteTime() + 3000;
    }
    sound.setMaxLength(Math.max(len, 60000));  //最少60s


    var htmls = [];
    for(var i=0;i<notes.length;i++){
        var note = notes[i];

        var html = this.makeNoteDiv(note);
        htmls.push(html);
    }
    this.note.append(htmls.join(''));

    this.updateGrid();
    this.needUpdate = true;
    this.onUpdate();
    //完全同步时, 自动获得焦点
    if(!this.focus){
        this.focus = true;
        event.trigger(event.events.global.blur, null, this);
    }
};

GridUI.prototype.updateGrid = function() {
	this._updateGrid();
    this.updateMusicbar();
};

GridUI.prototype.initSeekQueue = function(){
    var notes = this.manager.getNotes();
    this.unplayedNote = [];
    this.playedNote = [];
    this.playingNote = new Array(16);
    this.lastSeekTime = -1;
    for(var i =0;i<notes.length;i++){
        var note = notes[i];
        //把一个note拆成两份头和尾 和taiko不同的是pad模式只有2个队列 没有playing状态，当首尾节点分在两个队列中则表示正在播放中
        if(!note.endbeat){
            this.unplayedNote.push({
                realNote : note,
                time : note.time - this.fadeInTime
            });
            this.unplayedNote.push({
                realNote : note,
                time : note.time + this.fadeOutTime
            });
        }else{
            this.unplayedNote.push({
                realNote : note,
                time : note.time - this.fadeInTime
            });
            this.unplayedNote.push({
                realNote : note,
                time : note.endtime + this.fadeOutTime
            });
        }
    }
    console.log("init seek queue with obj length = " + (this.unplayedNote.length + this.playedNote.length));
    this.unplayedNote.sort(function(a, b){
        return a.time > b.time ? 1 : -1;
    });
};

GridUI.prototype.updateSeekQueue = function(){
    var currTime = sound.stableTime();
    var note;
    if(currTime > this.lastSeekTime){
        //播放或者前跳
        while(this.unplayedNote.length > 0){
            note = this.unplayedNote[0];
            if(currTime > note.time){
                this.updateBufferStat(note);
                this.playedNote.push(this.unplayedNote.shift());
            }else{
                break;
            }
        }
    }else{
        //后跳
        while(this.playedNote.length > 0){
            note = this.playedNote[this.playedNote.length - 1];
            if(currTime < note.time){
                this.updateBufferStat(note, true);
                this.unplayedNote.unshift(this.playedNote.pop());
            }else{
                break;
            }
        }
    }
    this.lastSeekTime = currTime;
};

GridUI.prototype.updateBufferStat = function(note, backward){
    var note = note.realNote;
    var index = note.index;
    var currNote = this.playingNote[index];
    if(!currNote){
        this.playingNote[index] = note;
    }else{
        if(note.id != currNote.id){
            //如果在同一个格子出现两个可以显示的note（出现交叠） 则根据是播放还是回退显示后一个或者前一个note
            if((!backward && note.time > currNote.time) || (backward && note.time < currNote.time)){
                this.playingNote[index] = note;
            }
        }else{
            //如果刷新的note id一致 则表示头尾各经过一次 置空格子
            this.playingNote[index] = null;
        }
    }
};

GridUI.prototype.reInitSeekQueue = function(){
    this.initSeekQueue();
    this.updateSeekQueue();
};

//完全刷新musicbar, 不要频繁使用
GridUI.prototype.updateMusicbar = function () {
    var notes = this.manager.getNotes();
    this.musicbar = {};
    for(var i=0;i<notes.length;i++){
        var note = notes[i];
        note.beat = frac.reduce(note.beat);

        if(note.index >= 0){
            var key = this.beatToKey(note.beat);
            if(key in this.musicbar){
                this.musicbar[key]++;
            }else{
                this.musicbar[key] = 1;
            }
        }
    }

    var htmls = [];
    var html;

    for(var key in this.musicbar){
        if(!this.musicbar.hasOwnProperty(key)){
            continue;
        }
        var beat = this.keyToBeat(key);
        var startY = frac.toFloat(beat) * this.gridScaleH;
        if(this.musicbar[key] > 8){
            html = '<i class="bar bar2" data-key="'+key+'" style="bottom:'+startY+'px;width:60px"></i>';
        }else{
            var w = this.musicbar[key] * 60 / 8;
            html = '<i class="bar" data-key="'+key+'" style="bottom:'+startY+'px;width:'+w+'px"></i>';
        }

        htmls.push(html);
    }
    this.barline.html(htmls.join(''));
};

//改变指定beat处的单个bar线
GridUI.prototype.changeMusicbar = function (beat, delta) {
    beat = frac.reduce(beat);
    var key = this.beatToKey(beat);
    if(key in this.musicbar){
        this.musicbar[key] += delta;
    }else{
        this.musicbar[key] = delta;
    }
    var item = this.barline.find('i[data-key="'+key+'"]');
    if(this.musicbar[key] <= 0){
        item.remove();
        delete this.musicbar[key];
    }else{
        if(item.size() == 0){
            item = $('<i class="bar" data-key="'+key+'"></i>');
            this.barline.append(item);
        }
        if(this.musicbar[key] > 8){
            item.css({
                bottom: frac.toFloat(beat) * this.gridScaleH,
                width: 60
            }).addClass('bar2');
        }else{
            item.css({
                bottom: frac.toFloat(beat) * this.gridScaleH,
                width: this.musicbar[key] * 60 / 8
            }).removeClass('bar2');
        }
    }
};

GridUI.prototype.onUpdate = function(){
    if(this._onUpdate()){
        return;
    }
    var self = this;
    this.updateSeekQueue();
    self.clearEditCanvas();
    self.drawNotes();
    this.barline.css('webkitTransform','translate3d(0,'+(this.noteAreaY - this._gridBtY)+'px,0)');
};

GridUI.prototype.makeNoteDiv = function(note){
    if(note.index !== undefined){
        return;
    }
    return this._makeNoteDiv(note);
};

GridUI.prototype.getSelectIds = function(args){
    var result = this._getSelectIds();
    for(var k in this.selectedNotes){
        if(this.selectedNotes.hasOwnProperty(k)){
            result.push(k);
        }
    }
    return result;
};

GridUI.prototype.cancelSelect = function(){
    this.selectedNotes = {};
    this._cancelSelect();
    this.updateSelectStatus();
};

GridUI.prototype.deleteSelect = function(){
    for(var i=0;i<16;i++){
        var note = this.playingNote[i];
        if(note && this.selectedNotes[note.id]){
            this.pluginPadEdit.removePadNote(note);
        }
    }
    for(var k in this.selectedNotes){
        this.pluginPadEdit.removePadNote(this.manager.getNote(k));
    }
    this.pluginMeta.update();
    this.reInitSeekQueue();
    this._deleteSelect();
};

/*
 * ================================ 事件处理 ================================
 */

GridUI.prototype.bindPadEvents = function(){
    this.padEditArea.on('mousedown', this.onPadMouseEvent.bind(this));
    this.padEditArea.on('mousemove', this.onPadMouseEvent.bind(this));
    this.padEditArea.on('mouseup', this.onPadMouseEvent.bind(this));
    event.bind(event.events.grid.bpm, 'pad_ui', this);
    event.bind(event.events.grid.interval, 'pad_ui', this);
    event.bind(event.events.grid.interval_change, 'pad_ui', this);
    event.bind(event.events.note.simplify, 'pad_ui', this);
};

GridUI.prototype.onEvent = function(e, param) {
    if(e == event.events.key.up) {
        if (!this.focus) {
            return;
        }
        switch (param.key) {
            case 27: //esc
                this.pluginPadEdit.selectPadNote(null);
                this.pluginPadEdit.cancelHoldDrawing();
                break;
            case 46: //del
                this.deleteSelect();
                break;
            case enums.KEY.A:
                this.selectAll();
                return event.result.stopAll;
        }
    }else if(e == event.events.grid.bpm){
        this.reCalcNoteTime();
    }else if(e == event.events.grid.interval){
        var dialog = require("../grid/dialog/min_interval");
        dialog.setManager(this.manager);
        dialog.show();
        return event.result.stopAll;
    }else if(e == event.events.grid.interval_change){
        this.drawNotes();
        return event.result.stopAll;
    }else if(e == event.events.note.simplify){
        var simplify = require('../note/simplify');
        simplify.init();
        simplify.setManager(this.manager);
        simplify.show();
        return event.result.stopAll;
    }
    this._onEvent(e, param);
};

GridUI.prototype.onPadMouseEvent = function(e){
    e.stopPropagation();
    switch(e.type){
        case 'mousedown':
            if(!this.focus) {
                this.focus = true;
            }
            this.pluginPadEdit.onPadMouseDown(e);
            break;
        case 'mousemove':
            this.pluginPadEdit.onPadMouseMove(e);
            break;
        case 'mouseup':
            this.pluginPadEdit.onPadMouseUp(e);
            //this.pluginMeta.update();
            break;
    }

};

GridUI.prototype.onParentEvent = function(e) {
    //屏蔽pad模式下的框选
    if($(e.currentTarget).attr("id") == "edit_up" && e.type == "mousemove"){
        return;
    }
    this._onParentEvent(e);
};
/*
 * ================================ Note操作函数 ================================
 */
GridUI.prototype.seekNotes = function(){
    var result = [];
    for(var i=0;i<this.playingNote.length;i++){
        var note = this.playingNote[i];
        if(note){
            result.push(note);
        }
    }
    return result;
};

GridUI.prototype.drawNotes = function(){
    var notes = this.seekNotes();
    this.padCanvas.clearRect(0, 0, (this._padW + 20)* 4 + 20, (this._padW + 20) * 4 + 20);
    this.updateGridNotes();
    this.updateSelectStatus();
};

GridUI.prototype.updateGridNotes = function(){
    var status = this.playingNote;
    for(var i=0;i<status.length;i++){
        var note = status[i];
        if(note){
            this.addTouchNoteDiv(note);
        }
    }
    if(this.pluginPadEdit.editData.currHoldNote){
        this.addTouchNoteDiv(this.pluginPadEdit.editData.currHoldNote);
    }
    // Hold line should be drawn after touch point, since they use the same canvas
    for(var i=0;i<status.length;i++){
        var note = status[i];
        if(note && note.endindex !== undefined){
            this.drawHoldLine(note);
        }
    }
};

GridUI.prototype.updateSelectStatus = function(){
    if($.isEmptyObject(this.selectedNotes)){
        return;
    }
    var status = this.playingNote;
    for(var i=0;i<status.length;i++){
        var note = status[i];
        var row = Math.floor(i / 4);
        var col = i % 4;
        if(note){
            if(this.selectedNotes[note.id]){
                this.padEditCanvas.lineWidth=2;
                this.padEditCanvas.strokeStyle = "#4190e7";
                this.padEditCanvas.roundRect(10+142*col ,10+142*row, 122, 122, 6).stroke();
            }
        }
    }
};

GridUI.prototype.drawHoldLine = function(note){
    var startPos = this.centerPos[note.index];
    var endPos = this.centerPos[note.endindex];
    //这里是左上角坐标而不是中心点 因为要贴图
    var half_w = 0.5 * this._padW;
    var sx = startPos[0] - half_w;
    var sy = startPos[1] - half_w;
    var ex = endPos[0] - half_w;
    var ey = endPos[1] - half_w;
    var endX,endY;
    var currTime = sound.stableTime();
    var countDown = parseInt(note.endtime - note.time - (currTime - note.time));
    var pct = countDown / (note.endtime - note.time);
    if(pct < 0) pct = 0;
    if(pct > 1) pct = 1;

    var ctx = this.padCanvas;

    var img = document.getElementById("pad_arrow");
    if(sx == ex){
        //纵向移动
        endY = sy + (ey - sy);
        var endY2 = sy + (ey - sy) * pct;
        endX = sx;
        var imgPos = sy < ey ? 600 : 200;
        ctx.drawImage(img,imgPos,0,200,200,sx,sy,122,122);
        ctx.drawImage(img,imgPos,0,200,200,endX,endY2,122,122);
        if(sy < ey){
            if(endY2 - sy - 122 > 0){
                ctx.drawImage(img,1000,0,200,200,sx,sy+122,122,endY2 - sy - 122);
            }
        }else{
            if(sy - endY2  - 122 > 0){
                ctx.drawImage(img,1000,0,200,200,sx,endY2+122,122,sy - endY2  - 122);
            }
        }

    }else if(sy == ey){
        //横向移动
        endX = sx + (ex - sx);
        var endX2 = sx + (ex - sx) * pct;
        endY = sy;
        var imgPos = sx < ex ? 400 : 0;
        ctx.drawImage(img,imgPos,0,200,200,sx,sy,122,122);
        ctx.drawImage(img,imgPos,0,200,200,endX2,endY,122,122);
        if(sx < ex){
            if(endX2 - sx - 122 > 0){
                ctx.drawImage(img,800,0,200,200,sx+122,ey,endX2 - sx - 122,122);
            }
        }else{
            if(sx - endX2  - 122 > 0){
                ctx.drawImage(img,800,0,200,200,endX2+122,ey,sx - endX2  - 122,122);
            }
        }
    }
    ctx.stroke();
    ctx.closePath();
};

GridUI.prototype.addTouchNoteDiv = function(note, flags){
    if(note.index === undefined ||  note.index > 15){
        return;
    }
    flags = flags || {};
    flags.isHold = flags.isHold || (note.endbeat != null);
    var currTime = sound.stableTime();
    var isHold = flags.isHold;
    if(!this.canDisplayNote(currTime, note) && !note.isDrawing && !flags.isMoving){
        return;
    }
    var frameStart = note.time - this.fadeInTime;
    var frameIndex = 0;
    if(!isHold){
        if(note.isDrawing){
            frameIndex = 16;
        }else{
            frameIndex = this.parseDigits(Math.ceil((currTime - frameStart) / (this.fadeInTime + this.fadeOutTime) * 25));
        }
    }else{
        if((note.time > currTime || note.endtime < currTime) && !note.isDrawing){
            var time = 0;
            time += currTime >= note.time ? this.fadeInTime : (this.fadeInTime - (note.time - currTime));
            time += currTime >= note.endtime ? (currTime - note.endtime) : 0;
            frameIndex = this.parseDigits(Math.ceil(time / (this.fadeInTime + this.fadeOutTime) * 25));
        }else{
            frameIndex = 16;
        }
    }
    var imgElement = document.getElementById('pad_img_' + frameIndex);
    var row = Math.floor(note.index / 4);
    var col = note.index % 4;
    if(imgElement){
        this.padCanvas.drawImage(imgElement, 10+142*col ,10+142*row, 122, 122);
    }
    var result = this.checkMinDistance(note);
    if(result.index !== null){
        this.padCanvas.fillStyle = "#0000ff";
        this.padCanvas.globalAlpha = 0.60;
        this.padCanvas.fillRect(10+142*col ,10+142*row, 122, 122);
        this.padCanvas.globalAlpha = 1;
    }
};

GridUI.prototype.addTouchNote = function(note, isHold){
    var _sound = sample.getCurrent();
    if(_sound){
        note.tid = -1;
        note.sound = _sound;
    }
    var time = this.pluginEdit.adjustNoteSound(note);
    this.checkMaxTime(time);
    this.manager.addNote(note);
    this.addTouchNoteDiv(note, {isHold: isHold});
    this.manager.sortNotes();
    this.changeMusicbar(note.beat, 1);
};

GridUI.prototype.canDisplayNote = function(time,note){
    if(!this.playingNote[note.index]){
        return true;
    }
    return this.playingNote[note.index].index == note.index;
};

GridUI.prototype.selectAll = function () {
    this.note.children().addClass('curr');
    var notes = this.manager.chart.note;
    for(var i=0;i<notes.length;i++){
        var note = notes[i];
        if(note.index != undefined){
            this.selectedNotes[note.id] = true;
        }
    }
    this.pluginMeta.update();
    this.updateSelectStatus();
};

GridUI.prototype.updateNotesPos = function (param) {
    this._updateNotesPos(param);
    for(var key in this.selectedNotes){
        if(!this.selectedNotes.hasOwnProperty(key))
            continue;
        var note = this.manager.getNote(+key);
        note.time = timing.beatToTime(note.beat);

        if(note.endbeat){
            note.endtime = timing.beatToTime(note.endbeat);
        }
        if(note.tid >= 0){
            var time = timing.beatToTime(note.beat) + (note.offset || 0);
            sound.offsetCell(note.tid, time);
            this.checkMaxTime(time);
        }
    }
    this.drawNotes();

    this.updateMusicbar();
};

/*
 * ================================ 辅助函数 ================================
 */
GridUI.prototype.cacheMarker = function(){
    //预读marker
    var htm = '<div style="display:none">';
    var basePath = config.getVal(config.ITEM.MARKER_PATH) || "static/img/marker/";
    for(var i=0;i<25;i++){
        var num = this.parseDigits(i+1);
        htm += '<img src="' + basePath + 'marker-' + num + '.png" id="pad_img_' + num + '">';
    }
    //hold arrows
    htm += '<img src="static/img/marker/holdarrow.png" id="pad_arrow">';
    htm += '</div>';
    $("body").append(htm);
};

GridUI.prototype.parseDigits = function(n){
    n = parseInt(n);
    return n < 10 ? "0" + n : n;
};

GridUI.prototype.beatToKey = function(beat) {
	return beat[0] + '-' + beat[1] + '-' + beat[2];
};

GridUI.prototype.keyToBeat = function(key) {
	var group = /(\d+)-(\d+)-(\d+)/.exec(key);
	if(group){
		return [+group[1], +group[2], +group[3]];
	}
	return [0,0,0];
};

GridUI.prototype.mousePosToBlockIndex = function(e){
    //将当前鼠标的位置转换为方块的索引号
    var px = e.pageX;
    var py = e.pageY;
    var x,y;
    for(var i=0;i<this.rowCount;i++){
        if(px >= this.blockOffsetX[i][0] && px <= this.blockOffsetX[i][1]){
            x = i;
            break;
        }
    }
    for(var j=0;j<this.rowCount;j++){
        if(py >= this.blockOffsetY[j][0] && py <= this.blockOffsetY[j][1]){
            y = j;
            break;
        }
    }
    return (x !== undefined) && (y !== undefined) ? (x + y*this.rowCount) : -1;
};

GridUI.prototype.calcBlockCenterPos = function(){
    var blockWidth = null;
    for(var i=0;i<this.rowCount;i++){
        for(var j=0;j<this.rowCount;j++){
            var block = this.getBlockByIndex(i*4 + j);
            if(!blockWidth){
                blockWidth = block.width();
            }
            this.centerPos.push([10 + 142*j + blockWidth /2, 10+142*i + blockWidth /2]);
        }
    }
};

GridUI.prototype.calcBlockOffset = function(){
    //计算16个格子中第一排和第一列的偏移 这样只要查表比对就知道当前鼠标位置对应的是第几个格子
    this.blockOffsetX = [];
    this.blockOffsetY = [];
    var blockWidth = null;
    for(var i=0;i<this.rowCount;i++){
        var blockX = this.getBlockByIndex(i);
        var blockY = this.getBlockByIndex(i*this.rowCount);
        if(!blockWidth){
            blockWidth = blockX.width();
        }
        var offsetX = blockX.offset();
        var offsetY = blockY.offset();
        this.blockOffsetX.push([offsetX.left , offsetX.left + blockWidth]) ;
        this.blockOffsetY.push([offsetY.top, offsetY.top + blockWidth]);
    }
};

GridUI.prototype.getBlockByIndex = function(index){
    return this.padEditArea.find("[index=" + index + "]");
};

GridUI.prototype.getSelectedNotesInScreen = function(){
    var rtn = [];
    for(var i=0;i<16;i++){
        var note =  this.playingNote[i];
        if(note && this.selectedNotes[note.id]){
            rtn.push(note);
        }
    }
    return rtn;
};

GridUI.prototype.reCalcNoteTime = function(){
    //在计时发生变化时重算note的开始、结束时间
    var notes = this.manager.chart.note;
    for(var i=0;i<notes.length;i++){
        var note = notes[i];
        note.time = timing.beatToTime(note.beat);

        if(note.endbeat){
            note.endtime = timing.beatToTime(note.endbeat);
        }
    }
};

GridUI.prototype.checkMinDistance = function(note){
    var notes = this.manager.chart.note;
    var minDist = this.manager.chart.extra.min_interval || 1033;
    var time = note.time;
    var index = null;
    var searchStart = false;
    for(var i=0;i<notes.length;i++){
        var obj = notes[i];
        if(obj.id == note.id || note.index != obj.index){
            continue;
        }
        var dist = Math.abs(obj.time - time);
        if(obj.endtime && obj.endtime < time){
            dist = Math.abs(obj.endtime - time);
        }
        if(dist < minDist){
            minDist = dist;
            index = obj.index;
            searchStart = true;
        }else{
            if(searchStart){
                break;
            }
        }
    }
    return {index : index, minDist: minDist};
};
/*
 * ================================ 画图函数 ================================
 */
GridUI.prototype.cavRemoveNote = function(index){
    var row = Math.floor(index / 4);
    var col = index % 4;
    this.padCanvas.clearRect(10+142*col ,10+142*row, 122, 122);
    this.cavRemoveSelectBox(index);
};

GridUI.prototype.cavRemoveSelectBox = function(index){
    var row = Math.floor(index / 4);
    var col = index % 4;
    this.padEditCanvas.clearRect(8+142*col ,8+142*row, 126, 126);
};

GridUI.prototype.clearEditCanvas = function(){
	this.padEditCanvas.clearRect(0, 0, (this._padW + 20)* 4 + 20, (this._padW + 20) * 4 + 20);
};

module.exports = GridUI;
